//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2008-10-24 16:56
 */
//========================================================================

#ifndef _PROACTOR_H_
#define _PROACTOR_H_
#include "Pre.h"

#include "Guard_T.h"
#include "ThreadMutex.h"
#include "AsynchIOImpl.h"
#include "GlobalMacros.h"
#include "ProactorImpl.h"

// Forward declarations.
class TimeValue;

/**
 * @class Proactor
 *
 * @brief The responsibility of this class is to forward all 
 * methods to its delegation/implementation class, e.g.
 * EpollProactor Win32Proactor
 */
class Proactor
{
public:
    /**
     * Constructor. If <impl> is 0, the correct implementation
     * object will be created. <delete_impl> flag determines
     * whether the implementation object should be deleted by the
     * Proactor or not.
     */
    Proactor (ProactorImpl *impl = 0,
	    int delete_impl = 0);

    // Destruction
    ~Proactor ();

    // Get pointer to a process-wide <Proactor> 
    static Proactor *instance ();

    // Set pointer to a process-wide <ACE_Proactor> and return existing
    // pointer.
    static Proactor *instance (Proactor * proactor, 
	    int delete_proactor = 0);

    // Delete the dynamically allocated Singleton.
    void close_singleton (void);

    // Run the event loop until the <Proactor::handle_events> 
    // method returns -1 or the <end_proactor_event_loop> method is invoked.
    int run_proactor_event_loop (void);

    // Instruct the Proactor to terminate its event loop
    // and notifies the Proactor so that it can wake up
    // and close down gracefully.
    void end_proactor_event_loop (void);

    // Report if the Proactor event loop is finished.
    int proactor_event_loop_done (void);

    // This method adds the <handle> to the I/O completion port. This
    // function is a no-op function for Unix systems and returns 0;
    int register_handle (NDK_HANDLE handle,
	    const void *completion_key,
	    int event_mask);

    /**
     * Dispatch a single set of events, waiting up to a specified time limit
     * if necessary. wait_time the time to wait for an event to occur. 
     * This is a relative time. 
     * Returns  0 if no events occur before the wait_time expires.
     * Returns >1 is the number of completions are dispatched. 
     * On error, returns -1
     */
    int handle_events (const TimeValue *wait_time);

    // Get number of thread used by proactor
    size_t number_of_threads (void) const;

    // Set number of thread used by proactor
    void number_of_threads (size_t threads);

    // Get the implementation class.
    ProactorImpl *implementation (void) const;

    // = Methods used to create Asynch IO factory and result objects. We
    // create the right objects here in these methods.
    AsynchReadStreamImpl *create_asynch_read_stream (void);
    AsynchReadStreamResultImpl *create_asynch_read_stream_result (
	    const AsynchHandler *asynch_handler,
	    NDK_HANDLE handle, 
	    MessageBlock *mb,
	    size_t bytes_to_read);

    //
    AsynchWriteStreamImpl *create_asynch_write_stream (void);
    AsynchWriteStreamResultImpl *create_asynch_write_stream_result (
	    const AsynchHandler *asynch_handler,
	    NDK_HANDLE handle,
	    MessageBlock *mb,
	    size_t bytes_to_write);

    //
    AsynchAcceptImpl *create_asynch_accept (void);
    AsynchAcceptResultImpl *create_asynch_accept_result (
	    const AsynchHandler *asynch_handler,
	    NDK_HANDLE listen_handle,
	    MessageBlock *mb,
	    size_t bytes_to_read);
protected:
    // Flag used to indicate whether we are responsible for cleaning up
    // the implementation instance.
    int delete_implementation_;

    // Delegation/implementation class that all methods will be
    // forwarded to.
    ProactorImpl *implementation_;

    static int delete_proactor_;

    // Pointer to a process-wide <Proactor>.
    static Proactor *proactor_;

    static ThreadMutex instance_lock_;
private:
    // Deny access since member-wise won't work...
    Proactor (const Proactor &);
    Proactor &operator= (const Proactor &);
};

#include "Proactor.inl"
#include "Post.h"
#endif

